import java.util.Random;
import java.util.Vector;
import javax.swing.JFrame;

import weka.core.*;
import weka.classifiers.Classifier;
import weka.classifiers.Evaluation;
import weka.classifiers.trees.*;
import weka.gui.treevisualizer.PlaceNode2;
import weka.gui.treevisualizer.TreeVisualizer;


public class DecisionTree{

            Database db;        
            Vector<Attribute> candidatAttr;
            Attribute goal;        
            double EntropyThres;
            double ScoreThres;
            Classifier tree;
            int code;
               
           
            DecisionTree(Database db, Vector<Attribute> candidatAttr, Vector<Integer> index, Attribute goal, int code, int mode, double percent)
            {
                this.db = db;      
                this.db.filterAttributes(index, goal);
                this.db.setTrain(mode, percent);
                this.db.train.setClassIndex(this.db.train.attribute(goal.name()).index());      
                this.code = code;
                this.goal = goal;
                initTree();
                buildTree();
               
            }
           
            DecisionTree(Database database, Vector<Attribute> candidatAttr, Attribute goal, double EntropyThres, double ScoreThres, int code)
            {
               
                this.EntropyThres = EntropyThres;
                this.ScoreThres = ScoreThres;
                this.db = database;
               
                this.candidatAttr = candidatAttr;
                this.goal = goal;
                this.code =code;
                initTree();
               
            }
           
            void initTree()
            {
                switch(code)
                {
                        case Constant.AD_TREE:
                                tree = new ADTree();
                                break;
                        case Constant.J48:
                                tree = new J48();
                                ((J48)tree).setNumFolds(10);
                                break;
                        case Constant.REPTree:
                                tree = new weka.classifiers.trees.REPTree();
                                break;
                        case Constant.J48graft:
                                tree = new weka.classifiers.trees.J48graft();
                                break;
                }      
            }
            
            
            void buildTree()
            {
                if(code == Constant.AD_TREE) 
                    if(goal.numValues() > 2)
                    {
                        String msg = new String("This methode is only applied with an attribute of 2 values");
                        System.out.println(msg);
                        Message mes = new Message("This methode is only applied with an attribute of 2 values");
                        mes.show();
                        return;
                    }
                
                try
                {      
                    tree.buildClassifier(db.train);            
                    visualiserTree();
                }
                catch(Exception e)
                {
                    System.out.println(e);
                    e.printStackTrace();
                }
            }
           
            
            
            void visualiserTree() throws Exception
            {
       
               
                String des = new String("");
                switch(code)
                {
                    case Constant.AD_TREE:
                            des = ((ADTree) tree).graph();
                            break;
                    case Constant.J48:
                            des = ((J48) tree).graph();
                            break;
                   case Constant.REPTree :
                	   des =((weka.classifiers.trees.REPTree)tree).graph();
                	   break;
                   case Constant.J48graft:
                	   des =((weka.classifiers.trees.J48graft)tree).graph();
                	   break;
                }
               
                TreeVisualizer tv = new TreeVisualizer(null, des, new PlaceNode2());
               
                tv.fitToScreen();
                tv.setSize(1200,400);

                DecisionTreeApplet.tp_show.removeAll();
                DecisionTreeApplet.tp_show.addTab("Weka Classifier Tree Visualizer: ADTree", tv);

                tv.fitToScreen();

            }
           
            String crossValidation()
            {
                String evaluation = new String("");
                if(tree != null)
                {
                	Evaluation eval;
                    try
                    {
                            int  folds = db.train.numInstances() > 10 ? 10 : db.train.numAttributes() /2;
                            eval = new Evaluation(db.train);
                            eval.crossValidateModel(tree, db.train, folds, new Random(1));                                  
                            evaluation = "Taux d'erreur = "+ eval.errorRate() + " \n " + eval.toSummaryString();                    
                    }
                    catch (Exception e)
                    {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    }
                }
                return evaluation;                      
            }
            
            
            String testTree()
            {          
                this.db.test.setClassIndex(this.db.test.attribute(goal.name()).index());        
               
                String evaluation = new String("");
                if(tree != null)
                {
                        Evaluation eval;
                                try
                                {
                                        eval = new Evaluation(db.test);                                
                                eval.evaluateModel(tree, db.test);                      
                                evaluation = "Taux d'erreur = "+ eval.errorRate() + " \n " + eval.toSummaryString();                            
                                }
                                catch (Exception e)
                                {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
                }              
                        return evaluation;              
            }
           
           
            Vector<String> prediction(Instances data)
            {
                data.setClassIndex(data.attribute(goal.name()).index());        
               
                String names = new String("");
                for(int i=0; i<data.numAttributes(); i++)
                        names+= data.attribute(i).name()+ " ";
               
                Vector<String> pred = new Vector();
                pred.add(names);
                pred.add(new String("================================================="));
               
                for(int i=0; i<data.numInstances(); i++)
                {
                    Instance inst = data.instance(i);
                    try
                    {
                        int a = (int)tree.classifyInstance(inst);
                        pred.add(data.instance(i).toString() + "  ->  [" + goal.value(a) + "]");                                        
                    }
                    catch (Exception e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }                              
                }              
                return pred;
            }
}

class Visualiser extends JFrame
{
        String content;
        java.awt.TextArea text = new java.awt.TextArea("");
       
    public Visualiser(String content)
    {
        super();
        this.content = content;
       
        this.add(text);
        text.setText(content);
        text.setVisible(true);
       
    }  
}